package TouristManagementBO.Site;

import java.util.Calendar;

import TouristManagement.*;

public class SiteImpl extends TouristManagement.SitePOA{
		
	private short idSite;	
	private VisitManagement leVisitManagement;	
	private ServerNamingTourist leServerNamingTourist;
	
	public SiteImpl(short idSite) {
		super();
		this.idSite = idSite;
	}
	
	public void initServer(){
		this.connectToServerNamingTourist();
		this.connectToVisitManagement();
	}
	
	/*
	 * connecter au server naming de l'application tourist
	 */
	public void connectToServerNamingTourist(){
		try {			
	        String args[]=null;
			org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
	        org.omg.CosNaming.NamingContext nameRoot =
	        org.omg.CosNaming.NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));	        
	        org.omg.CosNaming.NameComponent[] nameToFind = new org.omg.CosNaming.NameComponent[1];
	        nameToFind[0] = new org.omg.CosNaming.NameComponent("ServerNamingTourist","");
	        org.omg.CORBA.Object distantServerNamingTourist = nameRoot.resolve(nameToFind);
	        leServerNamingTourist = ServerNamingTouristHelper.narrow(distantServerNamingTourist);	        
	        System.out.println("Tourist naming server connected for site "+idSite);
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	/*
	 * connecter au server de visitmanagement
	 */
	public void connectToVisitManagement(){
		//init VisitManagement server
		try {
			String args[]=null;

			// Intialisation de l'orb
			org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);

	        // Recuperation du naming service
	        org.omg.CosNaming.NamingContext nameRoot =
	        		org.omg.CosNaming.NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));

	        // Construction du nom a rechercher
	        org.omg.CosNaming.NameComponent[] nameToFind = new org.omg.CosNaming.NameComponent[1];
	         nameToFind[0] = new org.omg.CosNaming.NameComponent(leServerNamingTourist.nomVisitManagement(),"");

	        // Recherche aupres du naming service
	        org.omg.CORBA.Object distantVisitManagement = nameRoot.resolve(nameToFind);

	        leVisitManagement = VisitManagementHelper.narrow(distantVisitManagement);

	        System.out.println("Objet VisitManagement connected for site "+idSite);
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	/*
	 * check in dans un site
	 */
	public short checkIn(short touristCardNumber) throws CheckInNotValid {
		//verify site condition
		if (leVisitManagement.getNbVisiteurMaximal(idSite) <= leVisitManagement.getNbVisiteurActuel(idSite))
		{
			throw new CheckInNotValid("Nombre visiteurs sur le site " + this.getNomSite() + " est maximal");
		}
		else {
			//if no saturation
			//get time 
			Calendar cal = Calendar.getInstance();
	    	short hour = (short) cal.get(Calendar.HOUR_OF_DAY);	  
	    	short minute = (short) cal.get(Calendar.MINUTE);	    	
	    	//checking opening and closing hour
	    	if (hour < this.getHoraireOuverture().hour || hour > this.getHoraireFermeture().hour
	    		|| (hour == this.getHoraireOuverture().hour && minute < this.getHoraireOuverture().minute)
	    			|| (hour == this.getHoraireFermeture().hour && minute > this.getHoraireFermeture().minute))
	    		{
	    		throw new CheckInNotValid("Not in opening hours");
	    	}	    	
	    	else {
	    		//verify validity of tourist
	    		DateV startValid = leVisitManagement.getDateDebValid(touristCardNumber);
	    		DateV endValid = leVisitManagement.getDateFinValid(touristCardNumber);	            

	    		Calendar start = Calendar.getInstance();
	    		start.set(Calendar.YEAR, startValid.year);
	    		start.set(Calendar.MONTH, startValid.month-1);
	    		start.set(Calendar.DATE, startValid.day);	    	    
	    	    
	    	    Calendar end = Calendar.getInstance();
	    	    end.set(Calendar.YEAR, endValid.year);
	    	    end.set(Calendar.MONTH, endValid.month-1);
	    	    end.set(Calendar.DATE, endValid.day);	    	    

	            //verify if the current date is between validity date
	            if (start.after(cal) || end.before(cal)){
	            	throw new CheckInNotValid("Invalid card");
	            }
	            else {
	            	//verify visit (tourist card number is valid or site visited...)
		    		boolean estVisite = leVisitManagement.verifyVisit(idSite,touristCardNumber);	    		
		    		
		    		if (estVisite) {
		    			throw new CheckInNotValid("Site visited");
		    		}
		    		else {			    		
				    	//update visit start hour in database
			    		leVisitManagement.addVisit(idSite,touristCardNumber);	
			    	}			    					    		
	    		}
	    	}
		}		
		return 0;
	}

	/*
	 * check out (sortir) d'un site
	 */
	public VisitManagement checkOut(short touristCardNumber) {
		//update visit exit hour 
		leVisitManagement.updateVisitEndHour(idSite,touristCardNumber);	
		return leVisitManagement;
	}

	/*
	 * consulter les statistiques locales du site
	 */
	public LocalStat consultLocalStat() {
		LocalStat localStat = new LocalStat();	
		localStat.affluenceQuotidienne = this.getAffluenceQuotidienne();
		localStat.durationAverage = this.getdurationAverage();
		localStat.durationMax = this.getdurationVisitMax();
		localStat.durationMin = this.getdurationVisitMin();
		return localStat;
	}

	/*
	 * vérifier si un tourist a déjà visité le site
	 */
	public boolean verifyVisit(short touristCardNumber) {
		return leVisitManagement.verifyVisit(idSite,touristCardNumber);
	}

	public short[] getIdSite() {
		return leVisitManagement.getIdSite();
	}

	@Override
	public Hours getHoraireOuverture() {		
		return leVisitManagement.getHoraireOuverture(idSite);
	}

	@Override
	public Hours getHoraireFermeture() {		
		return leVisitManagement.getHoraireFermeture(idSite);
	}

	@Override
	public short getNbVisiteurActuel() {		
		return leVisitManagement.getNbVisiteurActuel(idSite);
	}

	@Override
	public short getNbVisiteurMaximal() {		
		return leVisitManagement.getNbVisiteurMaximal(idSite);
	}

	@Override
	public short getdurationVisitMax() {		
		return leVisitManagement.getdurationMax(idSite);
	}

	@Override
	public short getdurationVisitMin() {		
		return leVisitManagement.getdurationMin(idSite);
	}
	
	@Override
	public Advice getAdviceAverage() {
		return leVisitManagement.getAdviceAverage(idSite);		
	}
	@Override
	public CoordsGPS getCoordsGPS() {
		return leVisitManagement.getCoordsGPS(idSite);		
	}

	@Override
	public short getdurationAverage() {
		return leVisitManagement.getdurationAverage(idSite);
	}

	@Override
	public short idSite() {
		return idSite;
	}

	@Override
	public String getNomSite() {
		return leVisitManagement.getNomSite(idSite);
	}

	/*
	 * get l'affluence quotidienne du site
	 */
	public short getAffluenceQuotidienne() {
		return leVisitManagement.getAffluenceQuotidienne(idSite);
	}

}
